/*!
        @file    action_F_Standard_SF.h

        @brief

        @author  Yusuke Taniguchi
                 $LastChangedBy: matufuru $

        @date    $LastChangedDate:: 2023-01-26 21:43:53 #$

        @version $LastChangedRevision: 2457 $
*/

#ifndef ACTION_FSTANDARD_SF_INCLUDED
#define ACTION_FSTANDARD_SF_INCLUDED

#include "Action/action.h"

#include "Force/Fermion/force_F.h"
#include "Solver/solver.h"

#include "Field/field_SF.h"

#include "IO/bridgeIO.h"
using Bridge::vout;

//! Standard fermion action with SF BC for HMC.

/*!
    This class defines an action with SF BC used in HMC.
    <ul>
    <li>Generated by copying Action_F_Standard class.
    <li>The argument Fopr and Force of the constructor should be implemented for the SF BC.
    <li>The only modification is in Action_F_Standard_SF::langevin
    <ul>
    <li>For the calculation of the initial Hamiltonian the pre-pseudo fermion field xi is set to zero at the boundary.
    <li>A private function set_boundary_zero(Field&) is introduced for this bounadry manipulation.
    <li>A few private members are added for this function.
    </ul>
    <li>The following properties are the same as those of the Action_F_Standard class.
    <ul>
    <li>Fermion and Force operators and given at the construction.
    <li>The solver is explicitly set to CG algorithm whose object is created in set_parameters().
    </ul>
    <li>[05 Apr 2012 Y.Yusuke]
    </ul>
    selector is implemented.       [02 Feb 2013 Y.Namekawa]
    (Selectors are replaced with factories by Aoyama-san)
    unique_ptr is introduced to avoid memory leaks
                                   [21 Mar 2015 Y.Namekawa]
 */

class Action_F_Standard_SF : public Action
{
 public:
  static const std::string class_name;

 private:
  Bridge::VerboseLevel m_vl;

  Fopr *m_fopr;
  Force *m_fopr_force;
  Field m_psf;
  std::string m_label;

  Solver *m_solver;

  Field *m_U;

  //! Needed to know a node at the temporal boundary.
  Communicator *comm;
  //! A spatial volume in a node.
  int Svol;
  //! number of the doubled color elements
  int m_Nc2;
  //! dimension of the spinor index
  int m_Nd;

  // A function to set the pseudo fermion field to zero at the t=0 boundary.
  //  void set_boundary_zero(Field&);

 public:
  Action_F_Standard_SF(Fopr *fopr, Force *fopr_force)
    : m_vl(CommonParameters::Vlevel()),
    m_fopr(fopr), m_fopr_force(fopr_force)
  {
    set_parameters();
  }

  Action_F_Standard_SF(Fopr *fopr, Force *fopr_force, const Parameters& params)
    : m_vl(CommonParameters::Vlevel()),
    m_fopr(fopr), m_fopr_force(fopr_force)
  {
    set_parameters(params);
  }

  ~Action_F_Standard_SF()
  {
    delete m_solver;
  }

  void set_parameters(const Parameters&);
  void set_parameters();

  void get_parameters(Parameters&) const;

  void set_label(const std::string label)
  {
    m_label = label;
    vout.detailed(m_vl, "  label: %s\n", m_label.c_str());
  }

  std::string get_label()
  {
    return m_label;
  }

  void set_config(Field *U)
  {
    m_U = U;
    m_fopr->set_config(U);
    m_fopr_force->set_config(U);
  }

  double langevin(RandomNumbers *);

  double calcH();

  void force(Field&);
};
#endif
